#include <bits/stdc++.h>
using namespace std;

/*
3484. 设计电子表格
已解答
中等
相关标签
premium lock icon
相关企业
提示
电子表格是一个网格，它有 26 列（从 'A' 到 'Z'）和指定数量的 rows。每个单元格可以存储一个 0 到 105 之间的整数值。

请你实现一个 Spreadsheet 类：

Spreadsheet(int rows) 初始化一个具有 26 列（从 'A' 到 'Z'）和指定行数的电子表格。所有单元格最初的值都为 0 。
void setCell(String cell, int value) 设置指定单元格的值。单元格引用以 "AX" 的格式提供（例如，"A1"，"B10"），其中字母表示列（从 'A' 到 'Z'），数字表示从 1 开始的行号。
void resetCell(String cell) 重置指定单元格的值为 0 。
int getValue(String formula) 计算一个公式的值，格式为 "=X+Y"，其中 X 和 Y 要么 是单元格引用，要么非负整数，返回计算的和。
注意： 如果 getValue 引用一个未通过 setCell 明确设置的单元格，则该单元格的值默认为 0 。

 

示例 1：

输入：
["Spreadsheet", "getValue", "setCell", "getValue", "setCell", "getValue", "resetCell", "getValue"]
[[3], ["=5+7"], ["A1", 10], ["=A1+6"], ["B2", 15], ["=A1+B2"], ["A1"], ["=A1+B2"]]

输出：
[null, 12, null, 16, null, 25, null, 15]

解释

Spreadsheet spreadsheet = new Spreadsheet(3); // 初始化一个具有 3 行和 26 列的电子表格
spreadsheet.getValue("=5+7"); // 返回 12 (5+7)
spreadsheet.setCell("A1", 10); // 设置 A1 为 10
spreadsheet.getValue("=A1+6"); // 返回 16 (10+6)
spreadsheet.setCell("B2", 15); // 设置 B2 为 15
spreadsheet.getValue("=A1+B2"); // 返回 25 (10+15)
spreadsheet.resetCell("A1"); // 重置 A1 为 0
spreadsheet.getValue("=A1+B2"); // 返回 15 (0+15)
 

提示：

1 <= rows <= 103
0 <= value <= 105
公式保证采用 "=X+Y" 格式，其中 X 和 Y 要么是有效的单元格引用，要么是小于等于 105 的 非负 整数。
每个单元格引用由一个大写字母 'A' 到 'Z' 和一个介于 1 和 rows 之间的行号组成。
总共 最多会对 setCell、resetCell 和 getValue 调用 104 次。
*/

// 法一
class Spreadsheet {
private:
    // 存储被修改过的单元格  k->单元格标识，v->当前值（未存储则默认0）
    unordered_map<string, int> cellMap;
    // helper  处理公式中的单个部分
    int getPartVal(const string& part) {
        // 单元格check
        if (isalpha(part[0]))   return cellMap.count(part) ? cellMap[part] : 0;
        else                    return stoi(part);
    }

public:
    // 指定行数，初始所有单元格值为0（无需额外操作，cellMap为空即表示默认0）
    Spreadsheet(int rows) {
        
    }
    
    void setCell(string cell, int value) {
        cellMap[cell] = value;  // 直接在映射中存储单元格-值对
    }
    
    void resetCell(string cell) {
        cellMap.erase(cell);
    }
    
    // 解析"=X+Y"格式，返回X和Y的和
    int getValue(string formula) {
        // 去除前缀的=
        string expr = formula.substr(1);

        // split + 
        size_t plusPos = expr.find('+');
        string leftPart = expr.substr(0, plusPos);  // 公式左半部分（X）
        string rightPart = expr.substr(plusPos + 1); // 公式右半部分（Y）

        // 求和
        return getPartVal(leftPart) + getPartVal(rightPart);
    }
};

/**
 * Your Spreadsheet object will be instantiated and called as such:
 * Spreadsheet* obj = new Spreadsheet(rows);
 * obj->setCell(cell,value);
 * obj->resetCell(cell);
 * int param_3 = obj->getValue(formula);
 */

// 法二
class Spreadsheet;

// 公式解析器：专门处理单元格标识和公式的解析，提高解析效率
class FormulaReader {
private:
    const std::string& s;     // 待解析的字符串（单元格标识或公式）
    const Spreadsheet& sheet; // 引用电子表格，用于获取单元格值
    int idx;                  // 当前解析位置索引

public:
    // 构造函数：绑定电子表格和待解析字符串，初始化解析位置
    FormulaReader(const Spreadsheet& sheet, const std::string& s)
        : sheet(sheet), s(s), idx(0) {}

    // 移动到下一个字符（用于跳过'='、'+'等非数据字符）
    void readChar() { ++idx; }

    // 读取列字母（A-Z），转换为0-25的索引（A->0，B->1...Z->25）
    int readLetter() { return s[idx++] - 'A'; }

    // 读取数字（行号或公式中的整数），转换为整数
    int readNum() {
        int n = 0;
        while (idx < s.size() && isdigit(s[idx])) { // 连续读取数字字符
            n = n * 10 + s[idx++] - '0';
        }
        return n;
    }

    // 解析单元格标识（如"A1"），返回{列索引, 行索引}（行号转为0-based）
    std::pair<int, int> readCellId() {
        int col = readLetter();  // 读取列（字母）
        int row = readNum() - 1; // 读取行号，转为0-based索引
        return {col, row};
    }

    // 读取单元格的值（通过解析单元格标识获取）
    int readCell();

    // 读取公式中的操作数（可能是单元格或数字）
    int readCellOrNum() {
        if (isalpha(s[idx])) { // 字母开头：是单元格
            return readCell();
        } else { // 数字开头：是整数
            return readNum();
        }
    }

    // 解析公式（格式"=X+Y"），返回X+Y的结果
    int readFormula() {
        readChar();                 // 跳过开头的'='
        int val1 = readCellOrNum(); // 读取第一个操作数
        readChar();                 // 跳过'+'
        int val2 = readCellOrNum(); // 读取第二个操作数
        return val1 + val2;         // 返回和
    }
};

// 电子表格类：管理26列（A-Z）×rows行的单元格数据
class Spreadsheet {
private:
    int rows;                           // 行数
    std::vector<std::vector<int>> data; // 存储单元格值：data[col][row]，初始为0

public:
    // 构造函数：初始化26列×rows行的网格，所有值默认为0
    Spreadsheet(int rows) : rows(rows), data(26, std::vector<int>(rows, 0)) {}

    // 重载()运算符：快速访问单元格（col=列索引，row=行索引）
    int& operator()(int col, int row) { return data[col][row]; }
    int operator()(int col, int row) const { return data[col][row]; }

    // 设置单元格值：解析单元格标识，更新对应位置的值
    void setCell(std::string cell, int value) {
        auto [col, row] = FormulaReader(*this, cell).readCellId(); // 解析单元格
        (*this)(col, row) = value;                                 // 更新值
    }

    // 重置单元格为0：解析单元格标识，将对应位置设为0
    void resetCell(std::string cell) {
        auto [col, row] = FormulaReader(*this, cell).readCellId(); // 解析单元格
        (*this)(col, row) = 0;                                     // 重置为0
    }

    // 计算公式值：通过FormulaReader解析并计算"=X+Y"格式的公式
    int getValue(std::string formula) {
        return FormulaReader(*this, formula).readFormula();
    }
};

// 实现readCell：通过解析单元格标识从电子表格获取值
int FormulaReader::readCell() {
    auto [col, row] = readCellId(); // 解析单元格的列和行索引
    return sheet(col, row);         // 从电子表格获取对应单元格的值
}